home *** CD-ROM | disk | FTP | other *** search
/ Resource for Source: C/C++ / Resource for Source - C-C++.iso / codelib4 / v_06_08 / v6n8037a.txt < prev    next >
Text File  |  1995-11-01  |  29KB  |  806 lines

  1. /******************************************************************************
  2. *
  3. *   File:       ASCII.H
  4. *
  5. *   Contents:   Definitions for standard ASCII values
  6. *
  7. ******************************************************************************/
  8.  
  9. #define NUL     0x00
  10. #define SOH     0x01
  11. #define STX     0x02
  12. #define ETX     0x03
  13. #define EOT     0x04
  14. #define ENQ     0x05
  15. #define ACK     0x06
  16. #define BEL     0x07
  17. #define BS      0x08
  18. #define HT      0x09
  19. #define LF      0x0A
  20. #define VT      0x0B
  21. #define FF      0x0C
  22. #define CR      0x0D
  23. #define SO      0x0E
  24. #define SI      0x0F
  25. #define DLE     0x10
  26. #define DC1     0x11
  27. #define DC2     0x12
  28. #define DC3     0x13
  29. #define DC4     0x14
  30. #define NAK     0x15
  31. #define SYN     0x16
  32. #define ETB     0x17
  33. #define CAN     0x18
  34. #define EM      0x19
  35. #define SUB     0x1A
  36. #define ESC     0x1B
  37. #define FS      0x1C
  38. #define GS      0x1D
  39. #define RS      0x1E
  40. #define US      0x1F
  41. #define SP      0x20
  42. #define DEL     0x7F
  43.  
  44.  
  45. /******************************************************************************
  46. *
  47. *   File:       USEFUL.H
  48. *
  49. *   Contents:   Declarations for USEFUL.LIB functions.
  50. *
  51. *   NOTE:   USEFUL.LIB contains general purpose functions that are missing
  52. *           from STDIO.LIB or that are useful to keep for future use.  This
  53. *           is only a partial header file.
  54. *
  55. ******************************************************************************/
  56.  
  57. char        *bld_ptr();         /* converts a segment token to a pointer    */
  58. unsigned    bld_sel();          /* converts a pointer to a token (selector) */
  59. char        *c_to_plm();        /* C string to PL/M (byte count) string     */
  60. int         fdelete();          /* delete a file                            */
  61. int         finfo();            /* get info about file (struct finfo_str)   */
  62. int         faccess();          /* change file access rights                */
  63.  
  64.  
  65. /*1****************************************************************************
  66. *
  67. *   File:       SPOOLER.C
  68. *
  69. *   Program:    Print Spooler Utility (for iRMX 286 OS)
  70. *
  71. *   Summary:    This print spooler will monitor the spooler directory for
  72. *               files.  As files are copied to the spooler directory, they
  73. *               will be copied to the system printer.  After a file has
  74. *               been copied to the printer, it will be deleted from the
  75. *               spooler directory.
  76. *
  77. *   Usage:  1.  Run the spooler as a background job under iRMX-286 R2.0:
  78. *
  79. *                   CREATEDIR :SD:SPOOLER       (if not already present)
  80. *
  81. *                   BACKGROUND(100,100) SPOOLER
  82. *
  83. *               Use "SPOOLER.LOG" as the name of the log file for the job.
  84. *
  85. *
  86. *           2.  Next, create a logical name for the spooler directory:
  87. *
  88. *                   ATTACHFILE :SD:SPOOLER AS :SPOOLER:
  89. *               (or)
  90. *                   ATTACHFILE :MASTER:SD/SPOOLER AS :SPOOLER:  (RMX-NET)
  91. *
  92. *
  93. *           3.  Finally, use the copy command to send files to the spooler:
  94. *
  95. *                   COPY SRC/ * TO :SPOOLER:
  96. *
  97. *   Caveats:    The spooler job sets itself up as a SUPER user so that it
  98. *               can have access to any file that is copied to the spooler
  99. *               directory.  Other than sending a form feed control to the
  100. *               printer before the start of each new file, the spooler
  101. *               does nothing but copy the files directly to the printer.
  102. *               All TAB conversions and paging should be performed before
  103. *               a file is copied to the spooler directory.
  104. *
  105. *   Author:     Richard Carver                  Date:   03/03/88
  106. *
  107. *   Revisions:
  108. *
  109. ******************************************************************************/
  110.  
  111. #include <rmx.h>                    /* RMX system call declarations */
  112. #include <ascii.h>                  /* ASCII control codes          */
  113. #include <stdio.h>                  /* Standard C Library           */
  114. #include <useful.h>                 /* Useful Functions Library     */
  115.  
  116.  
  117. /* RMX Condition Codes  */
  118.  
  119. #define E$OK                ((unsigned int)0x0000)
  120. #define E$TIME              ((unsigned int)0x0001)
  121. #define E$MEM               ((unsigned int)0x0002)
  122.  
  123.  
  124. /* Wait Times For RMX System Calls  */
  125.  
  126. #define NO_WAIT             ((unsigned int)0)
  127. #define WAIT_ONE_SEC        ((unsigned int)100)
  128. #define WAIT_TWO_SEC        ((unsigned int)200)
  129. #define WAIT_FOREVER        ((unsigned int)0xFFFF)
  130.  
  131.  
  132. /* Defines for various RMX system calls */
  133.  
  134. #define THIS_JOB            ((unsigned int)1)
  135. #define ROOT_JOB            ((unsigned int)3)
  136.  
  137. #define FIFO_MBX            ((unsigned int)0)
  138.  
  139. #define NO_RESP             ((unsigned int)0)
  140.  
  141. #define READ_ONLY           ((unsigned char)1)
  142. #define BUFFERS_TWO         ((unsigned char)2)
  143.  
  144. #define USER_SUPER          ((unsigned int)0)
  145.  
  146. #define ACCESS_DRAU         ((unsigned int)15)
  147.  
  148.  
  149. /* Miscellaneous Defines    */
  150.  
  151. #define DISABLE             ((unsigned char)0x00)
  152.  
  153. #define NOT_FOUND           ((int)-1)
  154.  
  155. #define PRINTER_NAME        ":LP:"
  156.  
  157. #define SPOOLER_MBX_NAME    "\013SPOOLER_MBX"
  158.  
  159.  
  160. /* Spooler Command Codes    */
  161.  
  162. #define CMND_CONTINUE       ((int)0)
  163. #define CMND_SUSPEND        ((int)1)
  164. #define CMND_SHUTDOWN       ((int)2)
  165. #define CMND_NEXTFILE       ((int)3)
  166.  
  167.  
  168. /* Spooler Commands */
  169.  
  170. char *spooler_cmnds[]   =   {   "continue",
  171.                                 "suspend",
  172.                                 "shutdown",
  173.                                 "nextfile",
  174.                                 NULL            };
  175.  
  176.  
  177. /* Structure Declarations   */
  178.  
  179. struct dir_entry_str                    /* RMX Directory Entry Structure    */
  180.     {
  181.     unsigned int    fnode;
  182.     char            fname[14];
  183.     };
  184.  
  185. struct finfo_str                        /* RMX File Information Structure   */
  186.     {
  187.     unsigned int        device_share;
  188.     unsigned int        number_connections;
  189.     unsigned int        number_reader;
  190.     unsigned int        number_writer;
  191.     unsigned char       share;
  192.     unsigned char       named_file;
  193.     char                device_name[14];
  194.     unsigned int        file_drivers;
  195.     unsigned char       functions;
  196.     unsigned char       flags;
  197.     unsigned int        device_granularity;
  198.     unsigned long int   device_size;
  199.     unsigned int        device_connections;
  200.     unsigned int        file_id;
  201.     unsigned char       file_type;
  202.     unsigned char       file_granularity;
  203.     unsigned int        owner_id;
  204.     unsigned long int   create_time;
  205.     unsigned long int   access_time;
  206.     unsigned long int   modify_time;
  207.     unsigned long int   file_size;
  208.     unsigned long int   file_blocks;
  209.     char                volume_name[6];
  210.     unsigned int        volume_granularity;
  211.     unsigned long int   volume_size;
  212.     unsigned int        accessor_count;
  213.     unsigned char       owner_access;
  214.     };
  215.  
  216. struct  user_ids_str                    /* RMX User ID Structure    */
  217.     {
  218.     unsigned int    length;
  219.     unsigned int    count;
  220.     unsigned int    user_id;
  221.     }user_ids   =   {1, 1, USER_SUPER};
  222.  
  223. struct xhndlr_str                       /* RMX Exception Handler Structure  */
  224.     {
  225.     void            (*xhndlr_addr)();
  226.     unsigned char   xhndlr_mode;
  227.     };
  228.  
  229. struct spooler_msg_str                  /* Spooler Message Structure    */
  230.     {
  231.     int         cmnd_code;
  232.     };
  233.  
  234.  
  235. /* Constant & Global Data   */
  236.  
  237. char    spooler_dir[]   =   "\013:sd:spooler";
  238.  
  239. int     spooler_state   =   CMND_CONTINUE;
  240.  
  241.  
  242. main(argc, argv)
  243. int     argc;
  244. char    *argv[];
  245.     {
  246.     int                     command;
  247.  
  248.     unsigned int            dummy_mbx;
  249.     unsigned int            root_tkn;
  250.     unsigned int            spooler_mbx;
  251.     unsigned int            rsp_mbx;
  252.     unsigned int            stat;
  253.     unsigned int            status;
  254.  
  255.     struct xhndlr_str       xhndlr_info;
  256.  
  257.     struct spooler_msg_str  *spooler_msg_ptr;
  258.  
  259. /*9****************************************************************************
  260. *       Disable the RMX exception handler.
  261. ******************************************************************************/
  262.  
  263.     rq$get$exception$handler(&xhndlr_info, &status);
  264.  
  265.     if (status == E$OK)
  266.         {
  267.         xhndlr_info.xhndlr_mode = DISABLE;
  268.  
  269.         rq$set$exception$handler(&xhndlr_info, &status);
  270.         }
  271.  
  272. /*9****************************************************************************
  273. *       Get the object token for the system's root job.  The root job is the
  274. *   highest level in the RMX job tree.
  275. ******************************************************************************/
  276.  
  277.     if (status == E$OK)
  278.         {
  279.         root_tkn = rq$get$task$tokens(ROOT_JOB, &status);
  280.         }
  281.  
  282.     if (status == E$OK)
  283.         {
  284. /*9****************************************************************************
  285. *       Lookup the name of the spooler mailbox in the root job's object
  286. *   directory.  This will be present only if the spooler is already installed.
  287. *   NOTE: RMX uses byte count strings (first byte in string is length).
  288. ******************************************************************************/
  289.  
  290.         spooler_mbx =
  291.             rq$lookup$object(root_tkn, SPOOLER_MBX_NAME, NO_WAIT, &status);
  292.  
  293.         if (status == E$OK)
  294.             {
  295. /*9****************************************************************************
  296. *       Since the spooler is installed, check to see if there are two command
  297. *   line arguments (program name and spooler command).  If there is only one
  298. *   argument (program name), inform user that the spooler is already running.
  299. *   If more than two arguments exist, the program was incorrectly invoked.
  300. ******************************************************************************/
  301.  
  302.             if (argc != 2)
  303.                 {
  304.                 if (argc == 1)
  305.                     {
  306.                     printf("ERROR: Spooler already installed.\n");
  307.                     }
  308.                 else
  309.                     {
  310.                     printf("ERROR: Invalid invocation.\n");
  311.                     }
  312.                 }
  313.             else
  314.                 {
  315. /*9****************************************************************************
  316. *       If the command invocation was correct, verify that the command is a
  317. *   valid command.  If an invalid command, indicate error.  If a valid
  318. *   command, create a message to send to the spooler.  Create a mailbox to
  319. *   receive the response from the spooler.  The response will use the same
  320. *   segment as the message.  Send the message to the spooler.  If the message
  321. *   could not be sent, the spooler is no longer running (it may have been
  322. *   deleted by the "kill" utility).  Remove the spooler mailbox name from
  323. *   the root directory so that the spooler may be re-installed in the future.
  324. *   If the message was sent, wait for the response from the spooler.  When
  325. *   the response has been received, delete the response mailbox and the
  326. *   message segment.
  327. ******************************************************************************/
  328.  
  329.                 command = command_code(argv[1]);
  330.  
  331.                 if (command == NOT_FOUND)
  332.                     {
  333.                     printf("ERROR: Invalid spooler command.\n");
  334.                     }
  335.                 else
  336.                     {
  337.                     spooler_msg_ptr =
  338.                         calloc(1, sizeof(struct spooler_msg_str));
  339.  
  340.                     if (spooler_msg_ptr != NULL)
  341.                         {
  342.                         spooler_msg_ptr->cmnd_code = command;
  343.  
  344.                         rsp_mbx = rq$create$mailbox(FIFO_MBX, &status);
  345.  
  346.                         if (status == E$OK)
  347.                             {
  348.                             rq$send$message(spooler_mbx,
  349.                                 bld_sel(spooler_msg_ptr), rsp_mbx, &status);
  350.  
  351.                             if (status != E$OK)
  352.                                 {
  353.                                 rq$uncatalog$object(
  354.                                     root_tkn, SPOOLER_MBX_NAME, &stat);
  355.                                 }
  356.                             else
  357.                                 {
  358.                                 rq$receive$message(rsp_mbx,
  359.                                     WAIT_FOREVER, &dummy_mbx, &status);
  360.                                 }
  361.  
  362.                             rq$delete$mailbox(rsp_mbx, &stat);
  363.                             }
  364.  
  365.                         free(spooler_msg_ptr);
  366.                         }
  367.                     else
  368.                         {
  369.                         status = E$MEM;
  370.                         }
  371.                     }
  372.                 }
  373.             }
  374.         else if (status == E$TIME)
  375.             {
  376. /*9****************************************************************************
  377. *       If the spooler mailbox name was not found (lookup timed out), then
  378. *   the spooler is not installed.  If only the program name was entered (one
  379. *   command line argument) then this invocation of the program will become
  380. *   the installed spooler.  Otherwise, nothing can be done because the
  381. *   spooler is not installed.
  382. ******************************************************************************/
  383.  
  384.             if (argc == 1)
  385.                 {
  386.                 spooler(root_tkn);
  387.                 }
  388.             else
  389.                 {
  390.                 printf("ERROR: Spooler not installed.\n");
  391.                 status = E$OK;
  392.                 }
  393.             }
  394.         }
  395.  
  396. /*9****************************************************************************
  397. *       If any RMX errors occurred during execution, display an error
  398. *   message.  Finally, exit the program.
  399. ******************************************************************************/
  400.  
  401.     if (status != E$OK)
  402.         {
  403.         printf("ERROR (%04xh): Could not execute spooler command.\n",
  404.             status);
  405.         }
  406.  
  407.     exit(0);
  408.     }
  409.  
  410. /*1****************************************************************************
  411. *
  412. *   Function:   command_code
  413. *
  414. *   Summary:    Searches the array of valid commands for a match on the
  415. *               given command.
  416. *
  417. *   Invocation: code = command_code(cmnd_ptr)
  418. *
  419. *   Inputs:     cmnd_ptr (char *) - address of command to search for
  420. *
  421. *   Outputs:    code (int) - returns NOT_FOUND (-1), if the command
  422. *                   was not found in the array of valid commands;
  423. *                   Otherwise, the value is the code for the command.
  424. *
  425. ******************************************************************************/
  426.  
  427. command_code(cmnd_ptr)
  428. char    *cmnd_ptr;
  429.     {
  430.     int     code;
  431.     int     indx;
  432.  
  433.     code = NOT_FOUND;
  434.  
  435.     for (indx = 0; (spooler_cmnds[indx] != NULL) &&
  436.         (code == NOT_FOUND); indx++)
  437.         {
  438.         if (strcmp(cmnd_ptr, spooler_cmnds[indx]) == 0)
  439.             {
  440.             code = indx;
  441.             }
  442.         }
  443.  
  444.     return (code);
  445.     }
  446.  
  447. /*1****************************************************************************
  448. *
  449. *   Function:   spooler_commands
  450. *
  451. *   Summary:    Check for any spooler commands
  452. *
  453. *   Invocation: spooler_state = spooler_commands(spooler_mbx)
  454. *
  455. *   Inputs:     spooler_mbx (unsigned int) - the token for the mailbox
  456. *                   where spooler commands will be received.
  457. *
  458. *   Outputs:    spooler_state (int) - the current command state of the
  459. *                   spooler (ie. shutdown, continue)
  460. *
  461. ******************************************************************************/
  462.  
  463. spooler_commands(spooler_mbx)
  464. unsigned int    spooler_mbx;
  465.     {
  466.     int                     command;
  467.  
  468.     unsigned int            rsp_mbx;            /* command response mailbox */
  469.     unsigned int            msg_tkn;            /* command message token    */
  470.     unsigned int            status;
  471.  
  472.     struct spooler_msg_str  *spooler_msg_ptr;
  473.  
  474. /*9****************************************************************************
  475. *       If a spooler shutdown is pending, then don't process any more
  476. *   commands.  Otherwise, check if a spooler command message is waiting
  477. *   to be processed.
  478. ******************************************************************************/
  479.  
  480.     if (spooler_state != CMND_SHUTDOWN)
  481.         {
  482.         command = CMND_CONTINUE;
  483.  
  484.         msg_tkn =
  485.             rq$receive$message(spooler_mbx, NO_WAIT, &rsp_mbx, &status);
  486.  
  487.         if (status == E$OK)
  488.             {
  489. /*9****************************************************************************
  490. *       If a command message was received, get the command code from the
  491. *   message and return to message to acknowledge the command was received.
  492. *   Then, process the command
  493. ******************************************************************************/
  494.  
  495.             spooler_msg_ptr = bld_ptr(msg_tkn);
  496.  
  497.             command = spooler_msg_ptr->cmnd_code;
  498.  
  499.             rq$send$message(rsp_mbx, msg_tkn, NO_RESP, &status);
  500.  
  501.             switch (command)
  502.                 {
  503. /*9****************************************************************************
  504. *       If the command is SUSPEND, then wait until a non-SUSPEND command
  505. *   is received.  If a problem occurs, shutdown the spooler.
  506. ******************************************************************************/
  507.  
  508.                 case CMND_SUSPEND:
  509.                     {
  510.                     while (command == CMND_SUSPEND)
  511.                         {
  512.                         msg_tkn = rq$receive$message(
  513.                             spooler_mbx, WAIT_FOREVER, &rsp_mbx, &status);
  514.  
  515.                         if (status == E$OK)
  516.                             {
  517.                             spooler_msg_ptr = bld_ptr(msg_tkn);
  518.  
  519.                             command = spooler_msg_ptr->cmnd_code;
  520.  
  521.                             rq$send$message(rsp_mbx,
  522.                                 msg_tkn, NO_RESP, &status);
  523.                             }
  524.                         else
  525.                             {
  526.                             command = CMND_SHUTDOWN;
  527.                             }
  528.                         }
  529.  
  530.                     break;
  531.                     }
  532.  
  533. /*9****************************************************************************
  534. *       Any other valid commands require no additional processing in this
  535. *   routine.  They will be passed back to the main spooler code.
  536. ******************************************************************************/
  537.  
  538.                 case CMND_SHUTDOWN:
  539.                 case CMND_CONTINUE:
  540.                 case CMND_NEXTFILE:
  541.                     {
  542.                     break;
  543.                     }
  544.  
  545. /*9****************************************************************************
  546. *       If an invalid command should get through, it will be handled like
  547. *   a CONTINUE command.  Which is basically a "do nothing" command.
  548. ******************************************************************************/
  549.  
  550.                 default:
  551.                     {
  552.                     command = CMND_CONTINUE;
  553.                     break;
  554.                     }
  555.                 }
  556.             }
  557.  
  558. /*9****************************************************************************
  559. *       Set the new state to the value of the command.
  560. ******************************************************************************/
  561.  
  562.         spooler_state = command;
  563.         }
  564.  
  565.     return (spooler_state);
  566.     }
  567.  
  568. /*1****************************************************************************
  569. *
  570. *   Function:   spooler
  571. *
  572. *   Summary:    The main code for the installed spooler job
  573. *
  574. *   Invocation: spooler(root_tkn)
  575. *
  576. *   Inputs:     root_tkn (unsigned int) - the token for the root job.
  577. *                   This is needed so that the spooler mailbox can be
  578. *                   catalogued in the root job's object directory.
  579. *
  580. *   Outputs:    none
  581. *
  582. ******************************************************************************/
  583.  
  584. spooler(root_tkn)
  585. unsigned int    root_tkn;
  586.     {
  587.     char                    buffer[128];    /* file I/O buffer              */
  588.     char                    fname[15];      /* file name ("C" format)       */
  589.  
  590.     int                     command;        /* spooler command code         */
  591.  
  592.     unsigned int            job_tkn;        /* spooler job token            */
  593.     unsigned int            user_tkn;       /* SUPER user object token      */
  594.     unsigned int            dir_con;        /* spooler directory connection */
  595.     unsigned int            status;         /* RMX condition code           */
  596.     unsigned int            byte_cnt;       /* bytes read from file         */
  597.     unsigned int            spooler_mbx;    /* spooler mailbox              */
  598.  
  599.     struct dir_entry_str    dir_entry;      /* RMX directory entry          */
  600.  
  601.     struct finfo_str        file_info;      /* file information data        */
  602.  
  603.     FILE                    *lp;            /* FILE pointer for printer     */
  604.     FILE                    *fp;            /* FILE pointer for file        */
  605.  
  606. /*9****************************************************************************
  607. *       Create and catalog the print spooler mailbox.
  608. *   NOTE: RMX uses byte count strings (first byte in string is length).
  609. ******************************************************************************/
  610.  
  611.     spooler_mbx = rq$create$mailbox(FIFO_MBX, &status);
  612.  
  613.     if (status == E$OK)
  614.         {
  615.         rq$catalog$object(root_tkn,
  616.             spooler_mbx, SPOOLER_MBX_NAME, &status);
  617.         }
  618.  
  619.     if (status != E$OK)
  620.         {
  621.         printf("ERROR (%04xh): Could not create spooler mailbox.\n",
  622.             status);
  623.         exit(1);
  624.         }
  625.  
  626. /*9****************************************************************************
  627. *       Setup the print spooler as a SUPER user.  The SUPER user can get
  628. *   access to files created by any system user.
  629. ******************************************************************************/
  630.  
  631.     job_tkn = rq$get$task$tokens(THIS_JOB, &status);
  632.  
  633.     if (status == E$OK)
  634.         {
  635.         user_tkn = rq$create$user(&user_ids, &status);
  636.  
  637.         if (status == E$OK)
  638.             {
  639.             rq$set$default$user(job_tkn, user_tkn, &status);
  640.             }
  641.         }
  642.  
  643.     if (status != E$OK)
  644.         {
  645.         printf("ERROR (%04xh): Could not setup spooler as a SUPER user.\n",
  646.             status);
  647.         exit(1);
  648.         }
  649.  
  650. /*9****************************************************************************
  651. *       Attach to the spooler directory and setup this directory as the
  652. *   default directory for future file accessing.
  653. *   NOTE: RMX uses byte count strings (first byte in string is length).
  654. ******************************************************************************/
  655.  
  656.     dir_con = rq$s$attach$file(spooler_dir, &status);
  657.  
  658.     if (status == E$OK)
  659.         {
  660.         rq$set$default$prefix(job_tkn, dir_con, &status);
  661.         }
  662.  
  663.     if (status != E$OK)
  664.         {
  665.         printf("ERROR (%04xh): Could not setup %s as spooler directory.\n",
  666.             status, &spooler_dir[1]);
  667.         exit(1);
  668.         }
  669.  
  670. /*9****************************************************************************
  671. *       Attach the system printer.
  672. ******************************************************************************/
  673.  
  674.     lp = fopen(PRINTER_NAME, "w");
  675.  
  676.     if (lp == NULL)
  677.         {
  678.         printf("ERROR: Could not attach the system printer\n");
  679.         exit(1);
  680.         }
  681.  
  682. /*9****************************************************************************
  683. *       Begin processing files that appear in the spooler directory until
  684. *   a shutdown command is received.  Each execution of this loop represents
  685. *   one complete pass through the spooler directory's "directory file".
  686. *   The directory file contains an entry for each file in the directory.
  687. *   It also may contain empty entries from delete files.  At the end of
  688. *   each pass, the directory file is closed.  Spooler commands are check
  689. *   for at various points.
  690. ******************************************************************************/
  691.  
  692.     command = spooler_commands(spooler_mbx);
  693.  
  694.     while ((status == E$OK) && (command != CMND_SHUTDOWN))
  695.         {
  696.         rq$s$open(dir_con, READ_ONLY, BUFFERS_TWO, &status);
  697.  
  698.         if (status == E$OK)
  699.             {
  700. /*9****************************************************************************
  701. *       Process directory entries until no more entries are found.
  702. ******************************************************************************/
  703.  
  704.             byte_cnt = rq$s$read$move(dir_con,
  705.                 &dir_entry, sizeof(dir_entry), &status);
  706.  
  707.             command = spooler_commands(spooler_mbx);
  708.  
  709.             while ((byte_cnt == sizeof(dir_entry)) &&
  710.                 (command == CMND_CONTINUE))
  711.                 {
  712. /*9****************************************************************************
  713. *       Copy the file name into a local buffer and convert it to a C string.
  714. *   If the entry is not empty (file node value is non-zero), then permit
  715. *   complete access to the file (Delete, Read, Append, Update).  It is
  716. *   possible that the file could still be in the process of being copied to
  717. *   the spooler directory, so wait until there a no users connected with the
  718. *   file.
  719. ******************************************************************************/
  720.  
  721.                 strncpy(fname, dir_entry.fname, (sizeof(fname) - 1));
  722.                 fname[sizeof(fname) - 1] = NUL;
  723.  
  724.                 if (dir_entry.fnode != 0)
  725.                     {
  726.                     faccess(fname, USER_SUPER, ACCESS_DRAU);
  727.  
  728.                     status = finfo(fname, &file_info);
  729.  
  730.                     if (status == E$OK)
  731.                         {
  732.                         while (file_info.number_connections > 0)
  733.                             {
  734.                             rq$sleep(WAIT_ONE_SEC, &status);
  735.                             finfo(fname, &file_info);
  736.                             }
  737.  
  738. /*9****************************************************************************
  739. *       Open the file, send a formfeed to the printer and begin copying the
  740. *   file to the printer.  Spooler commands will be checked for as each buffer
  741. *   of data is transfered to the printer.  A command other than CONTINUE, will
  742. *   terminate the printing of the file.  When printing if finish, possibly
  743. *   due to a command, the file is close, the printer buffer flushed, and the
  744. *   file deleted from the spooler directory.
  745. ******************************************************************************/
  746.  
  747.                         fp = fopen(fname, "r");
  748.  
  749.                         if (fp != NULL)
  750.                             {
  751.                             fputc(FF, lp);
  752.  
  753.                             byte_cnt = fread(buffer, 1, sizeof(buffer), fp);
  754.  
  755.                             command =
  756.                                 spooler_commands(spooler_mbx);
  757.  
  758.                             while ((byte_cnt > 0) &&
  759.                                 (command == CMND_CONTINUE))
  760.                                 {
  761.                                 fwrite(buffer, 1, byte_cnt, lp);
  762.  
  763.                                 byte_cnt =
  764.                                     fread(buffer, 1, sizeof(buffer), fp);
  765.  
  766.                                 command = spooler_commands(spooler_mbx);
  767.                                 }
  768.  
  769.                             fclose(fp);
  770.  
  771.                             fflush(lp);
  772.  
  773.                             fdelete(fname);
  774.                             }
  775.                         }
  776.                     }
  777.  
  778.                 byte_cnt = rq$s$read$move(dir_con,
  779.                     &dir_entry, sizeof(dir_entry), &status);
  780.  
  781.                 command = spooler_commands(spooler_mbx);
  782.                 }
  783.  
  784.             rq$s$close(dir_con, &status);
  785.             }
  786.  
  787.         rq$sleep(WAIT_TWO_SEC, &status);
  788.  
  789.         command = spooler_commands(spooler_mbx);
  790.         }
  791.  
  792. /*9****************************************************************************
  793. *       Spooler is being shutdown so cleanup before exiting.
  794. ******************************************************************************/
  795.  
  796.     rq$s$delete$connection(dir_con, &status);
  797.  
  798.     rq$uncatalog$object(root_tkn, SPOOLER_MBX_NAME, &status);
  799.     rq$delete$mailbox(spooler_mbx, &status);
  800.  
  801.     fclose(lp);
  802.  
  803.     exit(0);
  804.     }
  805.  
  806.